﻿using System;
using System.Linq;
using System.Text;

namespace CoreLibrary.Security {

    public class Encodings {

        private const string Base36CharList = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        public static readonly Encoding Gb2312 = Encoding.GetEncoding("gb2312");

        public static string ToBase64(string input) {
            return ToBase64(input, Encoding.UTF8);
        }

        public static string FromBase64(string base64String) {
            return FromBase64(base64String, Encoding.UTF8);
        }

        public static string ToBase64(string input, Encoding encoding) {
            return Convert.ToBase64String(encoding.GetBytes(input));
        }

        public static string FromBase64(string base64String, Encoding encoding) {
            return encoding.GetString(Convert.FromBase64String(base64String));
        }

        public static string ToHex(string input) {
            return BitConverter.ToString(Encoding.UTF8.GetBytes(input))
                               .Replace("-", string.Empty);
        }

        public static string FromHex(string hex) {
            if (string.IsNullOrEmpty(hex) || hex.Length % 2 != 0) {
                throw new ArgumentException("Input is not a hex string.");
            }

            return Encoding.UTF8.GetString(Enumerable.Range(0, hex.Length)
                                                     .Where(idx => idx % 2 == 0)
                                                     .Select(idx => Convert.ToByte(hex.Substring(idx, 2), 16))
                                                     .ToArray()
            );
        }

        public static string ToBase36(long number) {
            var sb = new StringBuilder();
            do {
                sb.Append(Base36CharList[(int)(number % 36)]);
                number /= 36;
            }
            while (number != 0);

            return new string(sb.ToString().Reverse().ToArray());
        }

        public static long FromBase36(string base36String) {
            long result = 0;
            var pow = 0;
            for (var i = base36String.Length - 1; i >= 0; i--) {
                 var c = base36String[i];
                 var pos = Base36CharList.IndexOf(c);
                 if (pos > -1) {
                    result += pos * (long)Math.Pow(Base36CharList.Length, pow);
                 } else {
                    return -1;
                 }
                 pow++;
            }
            return result;
        }

        
    }
}